// 1.

type Tree0729<T> = {
  value: T;
  children?: Tree0729<T>[];
};

const obj0729: Tree0729<string> = {
  value: "1", // 此处的值是根据Tree里面的泛型规定的类型
  children: [
    {
      value: "2",
      children: [
        {
          value: "3",
          children: [
            {
              value: "5",
            },
          ],
        },
      ],
    },
    {
      value: "4",
      children: [
        {
          value: "6",
        },
      ],
    },
  ],
};

// 2.1 声明一个函数类型 : 泛型参数是T 参数是T类型的可变数组 返回值是T
type Fn0729<T> = (...args: T[]) => T;
// 2.2 声明一个函数类型 : 泛型参数是<T,U> 要求U是T的key中的一项或者多项，返回值是T里面的具体值
type Fn07292<T, U extends keyof T> = () => T[U];

// {
//   username: 'zhangsan',
//   password : '1243'
// }

//3 .
type Float64Array0729<T, U> = {
  of: (args: T[]) => U[];
  prototype: {
    buffer: {
      props: string;
    };
  };
};

const example1: Float64Array0729<number, string> = {
  of(args: number[]): string[] {
    // 此处参数的返回值和泛型相关
    // 实现代码 返回偶数数组
    let arr = args.filter((item) => {
      if (item % 2 === 0) {
        return item;
      } else {
        return false;
      }
    }).map((item) => item + "");
    console.log(arr)
    return arr;
  },
  prototype: { buffer: { props: "props" } },
};

example1.of([1, 2, 3, 4, 5]);

// 
interface Todo0729 {
  title: string;
  description: string;
  completed: boolean;
}

type MyPick0729<T, U extends keyof T> = {
  [P in U] : T[P]
}

// 实现MyPick
type TodoPreview = MyPick0729<Todo0729, "title" | "completed">;

const todo: TodoPreview = {
  title: "Clean room",
  completed: false,
};


interface Example0729 {
	a: string;
	b: string | number;
	c: () => void;
}

type ConditionalPick<T,U> = {
  // as : 将一个值 当做 什么类型  {} as T
  // as : 在映射类型的后面 充当一个别名的角色 后面会跟着一个表达式 一定是条件类型
  // T P U
  // 属性后面的类型 T[P]  U
  // 条件表达式 : A extends B ? xxx : xxx
  // [P in keyof T as 条件表达式]
  [P in keyof T as T[P] extends U? P: never] : T[P]
}
// 测试用例：
type StringKeysOnly = ConditionalPick<Example0729, string>;
//=> {a: string}
const a0729 : StringKeysOnly ={
  a:'123',
}

// 6.
// extends : 1.对象  全面至少要包含后面的属性  2. 联合类型 一项一项比较
type MyNonNumber<T> = T extends number ? never : T// 去掉number类型
type MyNonNumberExample = MyNonNumber<string|number|undefined>;
const myNonNullable0729: MyNonNumberExample = undefined //string|undefined

